package com.example.redis.demo.controller;

import com.example.redis.demo.annotations.RequireAuth;
import com.example.redis.demo.dto.CheckDateSignDTO;
import com.example.redis.demo.dto.CheckSignDTO;
import com.example.redis.demo.dto.GetFirstSignDateDTO;
import com.example.redis.demo.dto.RegisterUserDTO;
import com.example.redis.demo.dto.UpdateUserInfoDTO;
import com.example.redis.demo.dto.UserSignDTO;
import com.example.redis.demo.exception.BusinessException;
import com.example.redis.demo.request.GetMyNearByRequest;
import com.example.redis.demo.request.RefreshTokenRequest;
import com.example.redis.demo.request.UpdateUserInfoRequest;
import com.example.redis.demo.request.UserLoginRequest;
import com.example.redis.demo.request.UserRegisterRequest;
import com.example.redis.demo.response.CheckDateSignResponse;
import com.example.redis.demo.response.CheckSignResponse;
import com.example.redis.demo.response.GetFirstSignDateResponse;
import com.example.redis.demo.response.GetMyNearByResponse;
import com.example.redis.demo.response.GetNearMeInfoResponse;
import com.example.redis.demo.response.RefreshTokenResponse;
import com.example.redis.demo.response.RegisterUserResponse;
import com.example.redis.demo.response.SignResponse;
import com.example.redis.demo.response.UserAuthResponse;
import com.example.redis.demo.response.UserInfoUpdateResponse;
import com.example.redis.demo.service.UserLoginLogService;
import com.example.redis.demo.service.UserService;
import com.example.redis.demo.service.UserSignService;
import com.example.redis.demo.util.JwtUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;

@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;


    @Autowired
    private UserSignService userSignService;


    @Autowired
    private UserLoginLogService userLoginLogService;

    /**
     * 用户签到接口
     *
     * @param userSignDTO
     * @return
     */
    @RequireAuth
    @PostMapping("/doSign")
    public SignResponse doSign(@RequestBody UserSignDTO userSignDTO, HttpServletRequest servletRequest) {
        String xToken = servletRequest.getHeader("x-token");
        if (xToken == null) {
            throw BusinessException.errorOfCode("需要传递用户token", "401");
        }
        String userName = JwtUtil.parseToken(xToken).get("userName").toString();
        Long userId = Long.valueOf(JwtUtil.parseToken(xToken).get("id").toString());
        userSignService.doSign(userId, userName, userSignDTO.getSignDate());
        return new SignResponse("200", "success", userSignDTO.getSignDate().toString());
    }

    /**
     * 检查某个用户是否在date这天是否已经签到过
     *
     * @param userSignDTO
     * @param servletRequest
     * @return
     */
    @PostMapping("/checkSign")
    public CheckSignResponse checkSign(@RequestBody CheckSignDTO userSignDTO, HttpServletRequest servletRequest) {
        String xToken = servletRequest.getHeader("x-token");
        if (xToken == null) {
            throw BusinessException.errorOfCode("需要传递用户token", "401");
        }
        Long userId = Long.valueOf(JwtUtil.parseToken(xToken).get("id").toString());
        boolean res = userSignService.checkSign(userId, userSignDTO.getDate());
        return new CheckSignResponse("200", "success", res);
    }


    /**
     * 检查当月一号到当天date的合计签到的总次数
     *
     * @param userSignDTO
     * @param servletRequest
     * @return
     */
    @PostMapping("/checkDateSign")
    public CheckDateSignResponse checkDateSign(@RequestBody CheckDateSignDTO userSignDTO, HttpServletRequest servletRequest) {
        String xToken = servletRequest.getHeader("x-token");
        if (xToken == null) {
            throw BusinessException.errorOfCode("需要传递用户token", "401");
        }
        Long userId = Long.valueOf(JwtUtil.parseToken(xToken).get("id").toString());
        long res = userSignService.getUserSignCount(userId, userSignDTO.getDate());
        return new CheckDateSignResponse("200", "success", res);
    }


    /**
     * 获取第一次签到的日期
     *
     * @param getFirstSignDateDTO
     * @param servletRequest
     * @return
     */
    @PostMapping("/getFirstSignDate")
    public GetFirstSignDateResponse getFirstSignDate(@RequestBody GetFirstSignDateDTO getFirstSignDateDTO, HttpServletRequest servletRequest) {
        String xToken = servletRequest.getHeader("x-token");
        if (xToken == null) {
            throw BusinessException.errorOfCode("需要传递用户token", "401");
        }
        Long userId = Long.valueOf(JwtUtil.parseToken(xToken).get("id").toString());
        String res = userSignService.getFirstSignMonthDay(userId, getFirstSignDateDTO.getDate());
        return new GetFirstSignDateResponse("200", "success", res);
    }


    /**
     * 需要认证授权才能访问的接口
     *
     * @param updateUserInfoDTO
     * @param httpServletRequest
     * @return
     */
    @RequireAuth(required = true) //需要鉴权
    @PostMapping("/updateUserInfo")
    public UserInfoUpdateResponse updateUserInfo(@RequestBody @Valid UpdateUserInfoDTO updateUserInfoDTO, HttpServletRequest httpServletRequest) {
        //1.这个接口是需要登录才能访问
        String xToken = httpServletRequest.getHeader("x-token");
        if (xToken == null) {
            throw BusinessException.errorOfCode("需要传递用户token", "401");
        }
        UpdateUserInfoRequest infoRequest = new UpdateUserInfoRequest();
        infoRequest.setEmail(updateUserInfoDTO.getEmail());
        infoRequest.setUserId(Long.valueOf(JwtUtil.parseToken(xToken).get("id").toString()));
        UserInfoUpdateResponse userInfoUpdateResponse = this.userService.updateUserInfo(infoRequest);
        return userInfoUpdateResponse;
    }


    @PostMapping("/register")
    public RegisterUserResponse register(@RequestBody @Valid RegisterUserDTO registerUserDTO) {
        final UserRegisterRequest userRegisterRequest = new UserRegisterRequest();
        userRegisterRequest.setUserName(registerUserDTO.getUserName());
        userRegisterRequest.setPassword(registerUserDTO.getPassword());
        userRegisterRequest.setEmail(registerUserDTO.getEmail());
        this.userService.register(userRegisterRequest);
        return new RegisterUserResponse("200", "success", true);
    }

    @PostMapping("/login")
    public UserAuthResponse login(@RequestBody @Valid UserLoginRequest userLoginRequest) {
        return this.userService.login(userLoginRequest);
    }


    @PostMapping("/refreshToken")
    public RefreshTokenResponse refreshToken(HttpServletRequest httpServletRequest) {
        String xToken = httpServletRequest.getHeader("refresh-token");
        if (xToken == null) {
            throw BusinessException.errorOfCode("需要传递用户token", "401");
        }
        final RefreshTokenRequest tokenRequest = new RefreshTokenRequest();
        tokenRequest.setRefreshToken(xToken);
        UserAuthResponse authResponse = this.userService.refreshToken(tokenRequest);
        RefreshTokenResponse.RefreshResult data = new RefreshTokenResponse.RefreshResult();
        data.setAccessToken(authResponse.getAccessToken());
        data.setAccessTokenExpiresIn(authResponse.getAccessTokenExpiresIn());
        return new RefreshTokenResponse("200", "success", data);
    }


    /**
     * 获取我的附近的人
     *
     * @return
     */
    @RequireAuth
    @PostMapping("/nearByMe")
    public GetMyNearByResponse getMyNearBy(@RequestBody GetMyNearByRequest getMyNearByRequest,
                                           HttpServletRequest servletRequest) {
        String xToken = servletRequest.getHeader("x-token");
        if (xToken == null) {
            throw BusinessException.errorOfCode("需要传递用户token", "401");
        }
        Long userId = Long.valueOf(JwtUtil.parseToken(xToken).get("id").toString());
        return userLoginLogService.getByUserIdAndDistance(userId, getMyNearByRequest.getM());
    }


    /**
     * 获取距离我最近的人
     *
     * @param getMyNearByRequest
     * @param servletRequest
     * @return
     */
    @RequireAuth
    @PostMapping("/nearestMe")
    public GetNearMeInfoResponse getNearestMe(@RequestBody GetMyNearByRequest getMyNearByRequest,
                                              HttpServletRequest servletRequest) {
        String xToken = servletRequest.getHeader("x-token");
        if (xToken == null) {
            throw BusinessException.errorOfCode("需要传递用户token", "401");
        }
        Long userId = Long.valueOf(JwtUtil.parseToken(xToken).get("id").toString());
        GetMyNearByResponse.NearByUser nearByUser = userLoginLogService.nearestMe(userId, getMyNearByRequest.getM());
        return new GetNearMeInfoResponse("200", "success", nearByUser);
    }


    /**
     * 获取距离我最近的人
     *
     * @param getMyNearByRequest
     * @param servletRequest
     * @return
     */
    @RequireAuth
    @PostMapping("/longestMe")
    public GetNearMeInfoResponse getLongestMe(@RequestBody GetMyNearByRequest getMyNearByRequest,
                                              HttpServletRequest servletRequest) {
        String xToken = servletRequest.getHeader("x-token");
        if (xToken == null) {
            throw BusinessException.errorOfCode("需要传递用户token", "401");
        }
        Long userId = Long.valueOf(JwtUtil.parseToken(xToken).get("id").toString());
        GetMyNearByResponse.NearByUser nearByUser = userLoginLogService.longestMe(userId, getMyNearByRequest.getM());
        return new GetNearMeInfoResponse("200", "success", nearByUser);
    }


}
